<template>
    <div>
        <el-upload
            ref="uploadRef"
            v-model:file-list="fileList"
            class="img-uploader"
            :action="uploadUrl"
            :limit="props.limit"
            :headers="headers"
            :show-file-list="showList"
            :disabled="disabled || loading"
            :on-success="successHandler"
            :list-type="showList ? 'picture-card' : 'text'"
            :on-error="errorHandler"
            :on-remove="removeHander"
            :on-progress="progressHandler"
            :on-exceed="handleExceed"
            :on-preview="pictureCardPreviewHandler"
            :before-upload="beforeUploadHandler">
            <div v-show="dialogImageUrl && !showList" @[event].stop class="has-upoload" v-loading="loading">
                <el-image class="has-upload-img" :src="dialogImageUrl" :fit="fit" />
                <div class="has-upload-icons">
                    <template v-if="!isChange">
                        <el-icon class="has-upload-icon-view" @click.stop="handlePictureCardPreview"
                            ><ZoomIn
                        /></el-icon>
                        <el-icon class="has-upload-icon-del" @click.stop="handleRemove"><Delete /></el-icon>
                    </template>
                    <template v-else>
                        <div class="has-upload-change">更换图片</div>
                    </template>
                </div>
            </div>
            <el-icon v-show="!dialogImageUrl || showList" v-loading="loading" class="img-uploader-icon"
                ><Plus
            /></el-icon>

            <template #tip>
                <div class="upload-tip" v-if="props.tipContent">
                    <el-icon color="#FF6B00" :size="16" class="tip-icon">
                        <InfoFilled />
                    </el-icon>
                    <span> {{ props.tipContent }} </span>
                </div>
            </template>
        </el-upload>
    </div>
    <el-dialog top="8vh" title="查看图片" v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" class="preview-img" />
    </el-dialog>
</template>

<script setup>
import { ref, reactive, inject, watch, computed } from 'vue';
import storage from '@/commons/storage.js';
import constants from '@/commons/constants';
import { ElMessage, genFileId } from 'element-plus';
const emit = defineEmits(['imgStateChange', 'update:modelValue']);

const props = defineProps({
    // 图片缩略图填充方式，默认占满
    fit: { type: String, default: 'fill' },
    // 是否禁用
    disabled: { type: Boolean, default: false },
    // tip
    tipContent: { type: String, default: '' },
    // 图片类型
    acceptTypes: { type: String, default: '.jpg,.png,.jpeg' },
    // 图片大小
    maxSize: { type: Number, default: 10 },
    // 其他校验条件
    validator: { type: Function, default: () => {} },
    // 已存在图片时
    currentImg: { type: [Array, String], default: '' },
    // 最大上传数
    limit: { type: Number, default: 1 },
    // 是否显示上传的文件列表
    showList: { type: Boolean, default: false },
    isChange: { type: Boolean, default: false },
    modelValue: {
        type: [Array, String],
        default: () => []
    },
    currentImgList: { type: Array, default: () => [] }
});
const headers = reactive({
    'ZW-PLATFORM-TOKEN': storage.get('ZW-TOKEN'),
    'ZW-TENANT-ID': storage.get('ZW-TENANT-ID')
});
const uploadRef = ref(null);
const fileList = ref([]);
let dialogImageUrl = ref('');
let dialogVisible = ref(false);
let imgUrl = ref('');
const tempUrl = constants.FILE_UPLOAD_URL;
let uploadUrl = ref(tempUrl);
let loading = ref(false);

const event = computed(() => {
    return props.isChange ? '' : 'click';
});

//监听外部传递进来的的数据变化或者做初始化用
watch(
    () => props.currentImg,
    () => {
        dialogImageUrl.value = props.currentImg;
    },
    {
        deep: true,
        immediate: true
    }
);
//监听上传图片，更新
watch(
    () => fileList.value.length,
    () => {
        emit('update:modelValue', fileList.value);
    },
    {
        deep: true
    }
);
//监听list
watch(
    () => props.currentImgList,
    () => {
        fileList.value.length = 0;
        fileList.value.push(...props.currentImgList);
    },
    {
        deep: true
    }
);
const beforeUploadHandler = file => {
    const acceptTypeArr = props.acceptTypes.split(',').map(x => {
        return 'image/' + x.replace('.', '');
    });
    // 考虑到服务端有文件类型和文件大小限制，所以这俩为必须校验
    if (!acceptTypeArr.includes(file.type)) {
        emitHandler({ msg: '请上传jpg、png、jpeg格式的图片' });
        return false;
    } else if (file.size / 1024 / 1024 > props.maxSize) {
        emitHandler({ msg: `图片大小应小于${props.maxSize}M` });
        return false;
    }
    return props.validator(file);
};

const handleRemove = () => {
    uploadRef.value.clearFiles();
    imgUrl.value = '';
    dialogImageUrl.value = '';
    emitHandler({ imgUrl });
};

// 列表删除
const removeHander = file => {};

// 列表预览
const pictureCardPreviewHandler = file => {
    if (props.showList) {
        dialogImageUrl.value = file.url;
        dialogVisible.value = true;
    }
};

const handlePictureCardPreview = () => {
    dialogVisible.value = true;
};

const handleExceed = files => {
    if (props.limit > 1 || !props.isChange) {
        return;
    }
    handleRemove();
    const file = files[0];
    file.uid = genFileId();
    uploadRef.value.handleStart(file);
    uploadRef.value.submit();
};

const successHandler = res => {
    if (!props.showList) {
        loading.value = false;
        if (res.code === 0) {
            imgUrl.value = res.data.url;
            dialogImageUrl.value = res.data.url;
            emitHandler({ imgUrl });
        } else {
            handleRemove();
            emitHandler({ msg: res.msg || '图片上传失败，请刷新重试！' });
        }
    } else {
        loading.value = false;
        res.msg &&
            res.code !== 0 &&
            ElMessage({
                type: 'error',
                message: '图片上传失败，请刷新重试！'
            });
    }
};

const errorHandler = res => {
    if (!props.showList) {
        loading.value = false;
        emitHandler({ msg: res.msg || '图片上传失败，请刷新重试' });
    } else {
        loading.value = false;
        res.msg &&
            ElMessage({
                type: 'error',
                message: '图片上传失败，请刷新重试！'
            });
    }
};

const progressHandler = () => {
    loading.value = true;
};

const emitHandler = ({ imgUrl, msg }) => {
    emit('imgStateChange', { imgUrl, msg });
};

defineExpose({
    loading
});
</script>

<style lang="scss" scoped>
.preview-img {
    width: 100%;
    border-style: none;
}
.upload-tip {
    font-size: 12px;
    line-height: 40px;
    width: 400px;
    word-break: break-all;
    color: #909399;
    .tip-icon {
        vertical-align: middle;
        margin-bottom: 4px;
    }
}
.img-uploader {
    :deep(.el-upload) {
        border: 1px dashed #dcdfe6;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
        transition: 0.2s;
        &:hover {
            border-color: var(--el-color-primary);
        }
    }

    .img-uploader-icon {
        font-size: 32px;
        width: 148px;
        height: 148px;
        text-align: center;
        color: var(--el-text-color-secondary);
        &:hover {
            color: var(--el-color-primary);
        }
    }
    .has-upoload {
        line-height: 0;
        .has-upload-img {
            width: 148px;
            height: 148px;
        }
        .has-upload-icons {
            position: absolute;
            width: 100%;
            height: 100%;
            left: 0;
            top: 0;
            cursor: default;
            display: inline-flex;
            justify-content: center;
            align-items: center;
            color: #fff;
            opacity: 0;
            font-size: 26px;
            background-color: var(--el-overlay-color-lighter);
            transition: opacity var(--el-transition-duration);
            &:hover {
                opacity: 1;
            }
            .has-upload-icon-view {
                margin-right: 5px;
                cursor: pointer;
            }
            .has-upload-icon-del {
                margin-left: 5px;
                cursor: pointer;
            }

            .has-upload-change {
                cursor: pointer;
                width: 100%;
                height: 100%;
                font-size: 13px;
                font-family: PingFangSC-Regular, PingFang SC;
                font-weight: 400;
                color: #ffffff;
                display: inline-flex;
                justify-content: center;
                align-items: center;
                user-select: none;
                background-color: rgba(0, 0, 0, 0.1);
            }
        }
    }
}
</style>
